package com.example.zlpermissionservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.zlpermissionservice.common.base.PageResponse;
import com.example.zlpermissionservice.common.constant.CommonConstant;
import com.example.zlpermissionservice.common.exception.BaseException;
import com.example.zlpermissionservice.dto.request.RoleReqDTO;
import com.example.zlpermissionservice.dto.response.ResourceResDTO;
import com.example.zlpermissionservice.dto.response.RoleResDTO;
import com.example.zlpermissionservice.entity.Resource;
import com.example.zlpermissionservice.entity.Role;
import com.example.zlpermissionservice.entity.RoleResource;
import com.example.zlpermissionservice.entity.UserRole;
import com.example.zlpermissionservice.mapper.RoleMapper;
import com.example.zlpermissionservice.service.IResourceService;
import com.example.zlpermissionservice.service.IRoleResourceService;
import com.example.zlpermissionservice.service.IRoleService;
//import com.github.pagehelper.Page;
//import com.github.pagehelper.PageHelper;
import com.example.zlpermissionservice.service.IUserRoleService;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author zhenliu（孙凌岳）
 * @Description TODO
 * @Date 2025/6/14 19:41
 * @Version 1.0
 */
@Service
@Slf4j
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
    @javax.annotation.Resource
    private RoleMapper roleMapper;

    @javax.annotation.Resource
    private IResourceService resourceService;

    @javax.annotation.Resource
    private IRoleResourceService roleResourceService;

    @javax.annotation.Resource
    private IUserRoleService userRoleService;

    /**
     * 多条件查询角色表分页列表
     * @param roleReqDTO
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageResponse<RoleResDTO> findRolePage(RoleReqDTO roleReqDTO, int pageNum, int pageSize) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(roleReqDTO.getRoleName())) {
            queryWrapper.like("role_name", roleReqDTO.getRoleName());
        }

        if (ObjectUtil.isNotEmpty(roleReqDTO.getLabel())) {
            queryWrapper.eq("label", roleReqDTO.getLabel());
        }

        if (ObjectUtil.isNotEmpty(roleReqDTO.getDataState())) {
            queryWrapper.eq("data_state", roleReqDTO.getDataState());
        }

        //降序排列
        queryWrapper.orderByAsc("sort_no");

        //构造分页对象
        Page<Role> page = new Page<>(pageNum, pageSize);
        //查询信息
        roleMapper.selectPage(page, queryWrapper);
        //封装信息
        PageResponse<RoleResDTO> pageResponse = PageResponse.of(page,RoleResDTO.class);


        // 角色资源装配
        if (!CollUtil.isEmpty(pageResponse.getRecords())) {
            List<Long> roleIds = pageResponse.getRecords().stream().map(RoleResDTO::getId).collect(Collectors.toList());

            // 查询资源列表
            List<ResourceResDTO> resourceList = resourceService.findResourceResDTOListInRoleId(roleIds);

            // 装配资源
            pageResponse.getRecords().forEach(role -> {
                Set<String> resourceNos = Sets.newHashSet();
                for (ResourceResDTO res : resourceList) {
                    if (String.valueOf(role.getId()).equals(res.getRoleId())) {
                        resourceNos.add(res.getResourceNo());
                    }
                }
                if (!resourceNos.isEmpty()) {
                    role.setCheckedResourceNos(resourceNos.toArray(new String[0]));
                }
            });
        }

        return pageResponse;
    }

    /**
     * 修改角色表
     * @param roleReqDTO
     * @return
     */
    @Override
    @Transactional
    public Boolean updateRole(RoleReqDTO roleReqDTO) {
        //转换RoleVo为Role
        Role role = BeanUtil.toBean(roleReqDTO, Role.class);
        role.setUpdateTime(LocalDateTime.now());

        if (ObjectUtil.isNotEmpty(role.getDataState()) && role.getDataState().equals("1")) {
            if (countUserRoleByRoleId(role.getId()) > 0) {
                throw new RuntimeException("该角色已分配用户,不能禁用");
            }
        }

        //更新角色信息
        boolean updateResult = lambdaUpdate()
                .eq(Role::getId, role.getId())
                .set(ObjectUtil.isNotEmpty(role.getRoleName()), Role::getRoleName, role.getRoleName())
                .set(ObjectUtil.isNotEmpty(role.getLabel()), Role::getLabel, role.getLabel())
                .set(ObjectUtil.isNotEmpty(role.getSortNo()), Role::getSortNo, role.getSortNo())
                .set(ObjectUtil.isNotEmpty(role.getDataState()), Role::getDataState, role.getDataState())
                .set(ObjectUtil.isNotEmpty(role.getUpdateTime()), Role::getUpdateTime, role.getUpdateTime())
                .set(ObjectUtil.isNotEmpty(role.getRemark()), Role::getRemark, role.getRemark())
                .set(ObjectUtil.isNotEmpty(role.getCreateBy()), Role::getCreateBy, role.getCreateBy())
                .set(ObjectUtil.isNotEmpty(role.getUpdateBy()), Role::getUpdateBy, role.getUpdateBy())
                .set(ObjectUtil.isNotEmpty(role.getDataScope()), Role::getDataScope, role.getDataScope())
                .update();

        if (!updateResult){
            throw new RuntimeException("修改角色信息出错");
        }

        if (ObjectUtil.isNotEmpty(role.getDataState())) {
            return true;
        }

        if (ObjectUtil.isEmpty(roleReqDTO.getDataScope())) {
            //删除原有角色资源中间信息
            Boolean delete = roleResourceService.deleteRoleResourceByRoleId(role.getId());
            if(!delete){
                throw new RuntimeException("删除角色资源关联信息信息出错");
            }

            //保存角色资源中间信息
            if (roleReqDTO.getCheckedResourceNos() == null || roleReqDTO.getCheckedResourceNos().length == 0) {
                return true;
            }
            List<RoleResource> roleResourceList = Lists.newArrayList();
            Arrays.asList(roleReqDTO.getCheckedResourceNos()).forEach(n->{
                RoleResource roleResource = RoleResource.builder()
                        .roleId(role.getId())
                        .resourceNo(n)
                        .dataState(CommonConstant.DATA_STATE_0)
                        .createTime(LocalDateTime.now())
                        .build();
                roleResourceList.add(roleResource);
            });
            if (roleResourceList.size() == 0) {
                return true;
            }
            boolean save = roleResourceService.saveBatch(roleResourceList);
            if (!save){
                throw  new RuntimeException("保存角色资源中间信息失败");
            }
            return true;
        }

//        //删除原有角色数据权限:这里不需要判断返回结果，有可能之前就没有自定义数据权限
//        roleDeptService.deleteRoleDeptByRoleId(role.getId());
//        //保存先的数据权限
//        if (SecurityConstant.DATA_SCOPE_0.equals(roleDto.getDataScope())){
//            //保存角色部门中间信息
//            List<RoleDept> roleDeptList = Lists.newArrayList();
//            Arrays.asList(roleDto.getCheckedDeptNos()).forEach(n->{
//                RoleDept roleDept = RoleDept.builder()
//                        .roleId(role.getId())
//                        .deptNo(n)
//                        .dataState(SuperConstant.DATA_STATE_0)
//                        .build();
//                roleDeptList.add(roleDept);
//            });
//            flag = roleDeptService.batchInsert(roleDeptList);
//            if (flag==0){
//                throw new RuntimeException("保存角色部门中间信息出错");
//            }
//        }
        return true;
    }

    /**
     * 根据id删除角色
     *
     * @param roleId
     * @return
     */
    @Override
    public Integer deleteRoleById(Long roleId) {
        if (countUserRoleByRoleId(roleId) > 0) {
            throw new BaseException("该角色已分配用户,不能删除");
        }
        // 删除角色与菜单关联
        roleResourceService.deleteRoleResourceByRoleId(roleId);
        return roleMapper.deleteById(roleId);
    }

    /**
     * 保存角色
     * @param roleReqDTO
     * @return
     */
    @Override
    @Transactional
    public RoleResDTO createRole(RoleReqDTO roleReqDTO) {
        //转换RoleVo为Role
        Role role = BeanUtil.toBean(roleReqDTO, Role.class);

        boolean save = this.save(role);
        if (!save){
            throw new RuntimeException("保存角色信息出错");
        }

        //拿回数据库生成的自增主键
        Long roleId = role.getId();

        //查询工作台信息
        List<Resource> resourceList = resourceService
                .lambdaQuery()
                .eq(Resource::getResourceName, "工作台")
                .list();

        List<RoleResource> roleResourceList = new ArrayList<>();

        //工作台资源包括很多按钮
        for(Resource resource : resourceList){
            //角色默认绑定工作台资源
            RoleResource roleResource = new RoleResource();
            roleResource.setDataState(CommonConstant.DATA_STATE_0);
            roleResource.setResourceNo(resource.getResourceNo());
            roleResource.setRoleId(roleId);
            roleResource.setCreateTime(LocalDateTime.now());
            roleResource.setUpdateTime(LocalDateTime.now());
            roleResource.setCreateBy(roleReqDTO.getCreateBy());
            roleResource.setUpdateBy(roleReqDTO.getUpdateBy());
            roleResource.setRemark("初始化角色含工作台资源");
            roleResourceList.add(roleResource);
        }

        boolean saveBatch = roleResourceService.saveBatch(roleResourceList);
        if(!saveBatch){
            throw new RuntimeException("保存初始化角色资源信息出错");
        }

        return BeanUtil.toBean(role, RoleResDTO.class);
    }

    /**
     * 注册流程-绑定默认角色
     * @param userId
     */
    @Override
    @GlobalTransactional
    public void bindDefaultRole(Long userId) {
        UserRole userRole = new UserRole();

        //查询默认角色信息
        Role defaultRole = this.lambdaQuery()
                .eq(Role::getLabel, CommonConstant.DEFAULT_ROLE)
                .one();
        if(ObjectUtil.isNull(defaultRole)){
            throw new BaseException("查询默认角色信息失败");
        }

        //构建用户角色关联信息
        userRole.setRoleId(defaultRole.getId());
        userRole.setUserId(userId);
        userRole.setCreateTime(LocalDateTime.now());
        userRole.setUpdateTime(LocalDateTime.now());

        //保存用户角色关联信息
        boolean save = userRoleService.save(userRole);
        if(!save){
            throw new BaseException("保存用户角色关联信息失败");
        }
    }

    /**
     * 根据用户id获取角色
     * @param userId
     * @return
     */
    @Override
    public Role getUserRole(Long userId) {
        return roleMapper.findByUserId(userId);
    }

    /**
     * 根据角色码获取角色id
     * @param roleCode
     * @return
     */
    @Override
    public Long getRoleIdByLabel(String roleCode) {
        if (StrUtil.isBlank(roleCode)) {
            return null;
        }
        Role role = roleMapper.findRoleIdByLabel(roleCode);
        return role.getId();
    }

    /**
     * 通过角色ID查询角色使用数量
     *
     * @param roleId 角色ID
     * @return 结果
     */
    public int countUserRoleByRoleId(Long roleId) {
        return roleMapper.countUserRoleByRoleId(roleId);
    }


    /**
     * 角色下拉框
     * @return
     */
    @Override
    public List<RoleResDTO> initRoles() {
        RoleResDTO roleResDTO = RoleResDTO.builder()
                .dataState(CommonConstant.DATA_STATE_0)
                .build();
        List<Role> roleList = lambdaQuery()
                .like(StrUtil.isNotBlank(roleResDTO.getRoleName()), Role::getRoleName, roleResDTO.getRoleName())
                .eq(StrUtil.isNotBlank(roleResDTO.getLabel()), Role::getLabel, roleResDTO.getLabel())
                .eq(StrUtil.isNotBlank(roleResDTO.getDataState()), Role::getDataState, roleResDTO.getDataState())
                .orderByAsc(Role::getSortNo)
                .list();
        return BeanUtil.copyToList(roleList,RoleResDTO.class);
    }

    /**
     *  查询用户对应角色
     * @param userId 查询条件
     * @return: List<Role>
     */
    @Override
    public List<RoleResDTO> findRoleResDTOListByUserId(Long userId) {
        return roleMapper.findRoleResDTOListByUserId(userId);
    }

    /***
     *  查询用户对应的角色
     * @param userIds
     * @return
     */
    @Override
    public List<RoleResDTO> findRoleResDTOListInUserId(List<Long> userIds) {
        return roleMapper.findRoleResDTOListInUserId(userIds);
    }
}
